﻿#region Using Statements
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework.Graphics;
using BreakOutBattles.IO;
using BreakOutBattles.IO.Net;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Input;
using Lidgren.Network;
using BreakOutBattles.Game;
#endregion

namespace BreakOutBattles.Menus
{
    public class JoinGameMenu : Menu
    {
        #region Fields
        private string[] editableFields = { "player", "8989", "localhost" };

        private IOManager ioManager;
        private GameNetClient gameNetClient;
        private NetworkManager networkManager;
        private JoinClientConfig matchConfiguation;
        private SpriteFont descriptionFont;
        private SpriteFont headingFont;
        private Vector2 playerNamePos;
        private Vector2 portPos;
        private Vector2 ipPos;
        #endregion

        public JoinGameMenu(Microsoft.Xna.Framework.Game game, SpriteBatch spriteBatch)
            : base(game, spriteBatch)
        { }

        #region Initialization
        /// <summary>
        /// 
        /// </summary>
        public override void Initialize()
        {
            base.Initialize();

            ioManager = IOManager.Instance;
            networkManager = NetworkManager.Instance;
            gameNetClient = NetworkManager.Instance.GameNetClient;
            matchConfiguation = new JoinClientConfig();

            descriptionFont = ioManager.LoadFont("descriptionFont");
            headingFont = ioManager.LoadFont("headingFont");

            playerNamePos = new Vector2(550, 100);
            portPos = new Vector2(550, 200);
            ipPos = new Vector2(550, 300);
        }

        /// <summary>
        /// Creates the menu items of this menu.
        /// </summary>
        public override void CreateMenu()
        {
            menuItems.Add(new MenuItem("Nickname: ", new Vector2(350, 100), new Action(delegate { })));
            menuItems.Add(new MenuItem("Port: ", new Vector2(350, 200), new Action(delegate { })));
            menuItems.Add(new MenuItem("IP: ", new Vector2(350, 300), new Action(delegate { })));
            menuItems.Add(new MenuItem("Join! ", new Vector2(600, 450), new Action(OnJoinGameAction)));
        }
        #endregion

        #region Menu Actions
        private void OnJoinGameAction()
        {
            matchConfiguation.PlayerName = editableFields[0];

            //Try to connect to the game server with the entered values.
            networkManager.GameNetClient = new GameNetClient(editableFields[0] + this.GetHashCode());
            networkManager.GameNetClient.ConnectedToServer += ConnectedToServer;
            networkManager.GameNetClient.Connect(true, editableFields[2].ToLower(), int.Parse(editableFields[1]));

            GameState.CurrentState = GameStates.HOST_WAIT;
        }
        #endregion

        #region Event Handling
        public void ConnectedToServer(object sender, object args)
        {
            //Register the joining player in the JoinManager.
            JoinManager.SecondaryPlayer = new Player();
            JoinManager.SecondaryPlayer.Name = editableFields[0];
            JoinManager.SecondaryPlayer.IsRemotePlayer = false;

            //Register the necesary event handlers to receive joining info from the server.
            networkManager.GameNetClient.HostConfigurationReceived += JoinManager.HostConfigurationReceived;

            //Send the joining client configuration to the other players.
            networkManager.GameNetClient.SendJoinClientConfigMessage(matchConfiguation);

            GameState.CurrentState = GameStates.PLAYER_JOIN_WAIT;
        }
        #endregion

        #region Input Handling
        /// <summary>
        /// Handles user interaction with the menu.
        /// </summary>
        protected override void HandleInput(GameTime gameTime)
        {
            base.HandleInput(gameTime);

            HandleAlphabeticKeyPressed();
        }

        /// <summary>
        /// Checks if an alphabetical key has been pressed, if so, the character mapped
        /// to the pressed key will be appended to the current player nickname.
        /// </summary>
        private void HandleAlphabeticKeyPressed()
        {
            if (currentMenuIndex != LastMenuIndex)
            {
                foreach (Keys key in keyboardState.GetPressedKeys())
                {
                    if (KeyPressed(key) && IsAlphabeticalKey(key))
                    {
                        char charToAppend = (char)key;

                        if (key == Keys.OemPeriod)
                        {
                            charToAppend = '.';
                        }
                        editableFields[currentMenuIndex] += charToAppend;
                    }
                }

                if (KeyPressed(Keys.Back))
                {
                    if (editableFields[currentMenuIndex].Length > 0)
                    {
                        editableFields[currentMenuIndex] = editableFields[currentMenuIndex].Substring(0, editableFields[currentMenuIndex].Length - 1);
                    }
                }
            }
        }
        #endregion

        /// <summary>
        /// Renders the menu.
        /// </summary>
        public override void Draw(GameTime gameTime)
        {
            base.Draw(gameTime);

            spriteBatch.DrawString(font, editableFields[0], playerNamePos, Color.Red);
            spriteBatch.DrawString(font, editableFields[1], portPos, Color.Red);
            spriteBatch.DrawString(font, editableFields[2], ipPos, Color.Red);
        }
    }
}
